承接上章,這篇繼續細講幾何階段/Geometry Stage和光柵化階段/Rasterizer Stage這兩個階段。
稍微複習一下,幾何階段接受模型座標的頂點資料,輸出螢幕座標的頂點資料;光柵化階段接受螢幕座標的頂點資料,輸出螢幕上的最終結果(像素)。
裡面的子Pipeline是這樣的:
其中,Unity把大部分的功能都封裝好了,我們在編寫Unity Shader時,只要配置一些設定,並撰寫Vertex Shader跟Fragment Shader就可以呈現大部分的視覺效果。
我們知道Geometry Stage最主要的功能就是將模型座標的頂點,轉換成映射在螢幕上座標。要完成這個轉換,中間依靠的就是Vertex Shader。
Vertex Shader的處理單位是頂點,每從CPU輸入一個頂點進來,就會調用一次Vertex Shader,將座標從模型座標轉換成世界座標(在OpenGL中是一個每邊為-1到1的單位立方體),再計算頂點的顏色。我們可以透過它實現頂點動畫,像是水面或是飄動的旗幟等等效果,也可以擴張頂點位置,決定物體的外框線效果的粗細。
Vertex Shader的結果是世界座標的頂點。那它又是怎麼被映射到螢幕上的呢?
首先我們先要使用Clipping,將不在相機範圍內、超出前述單位立方體的物體過濾掉。接下來,再透過螢幕映射(Screen Mapping),將x和y座標轉換成螢幕座標係。由於我們的數入來源是單位立方體,也就是一張方形圖片,所以Screen Mapping實際上是會經過拉伸的過程(畢竟我們的螢幕不太可能是正方形的嘛)。至於剩餘的y座標資訊,則是會和轉換成螢幕座標系的頂點一起作為窗口座標系(Window Coordinates)傳遞到光柵化階段。
進入光柵化階段之後,第一步就是藉由Triangle Setup畫出三角面,再透過Triangle Traversal將三角面切割成一塊塊的像素。這兩個階段最後輸出的結果,嚴格來說並不是真正意義上的像素,而是用來計算每個像素最終顏色的所有資訊的集合——片元/Fragment。
每個Fragment都會調用Fragment Shader,這也是另一個Unity可以讓我們自己客制的部分,像是外框線效果,透過Vertex Shader擴張頂點位置後,再用Fragment Shader塗上顏色。
Fragment Shder結束後,最後會再透過Pre-Fragment Operation,經過一連串的模板測試、深度測試,再將片元存在Color Buffer,最終輸出螢幕上的畫面,也就是我們的最終效果。